﻿
using GRPCClass;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SdtpsLibrary
{
    public class TaskHanle
    {
        private static int TaskMaxCount = 10000;
        public static System.Windows.Forms.Control viewctrl;
        public static void Show_ViewText(string Text)
        {
            if (viewctrl != null)
            {
                viewctrl.Invoke((MethodInvoker)(() =>
                {
                    if (viewctrl.Text.Length > 9000)
                    {
                        viewctrl.Text = "";
                    }
                    viewctrl.Text +=string.Format("{0}\t{1}\r\n",DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Text);
 
                }));
            }
        }
        /// <summary>
        /// 所有的任务列表
        /// </summary>
        public static GRPCClass.TaskRequestCollection TaskList = new GRPCClass.TaskRequestCollection();
        /// <summary>
        /// 任务处理结果
        /// </summary>
        public static GRPCClass.TaskReplyCollection TaskReplyList = new GRPCClass.TaskReplyCollection();
        /// <summary>
        /// 失败任务结果
        /// </summary>
        public static GRPCClass.TaskReplyCollection TaskReplyErrList = new GRPCClass.TaskReplyCollection();

        public static List<Worker> Workers = new List<Worker>();

        /// <summary>
        /// 未分配的任务列表
        /// </summary>
        public static TaskRequestCollection TaskNoAllotList = new TaskRequestCollection();
        public static int LastWorkNum = 0;
        public static Boolean AddTask(TaskRequest request,out string msg)
        {

            if (TaskList.Count > TaskMaxCount)
            {
                msg = "超出任务总数";    
                return false;
            }
            TaskList.Add(request);
            TaskNoAllotList.Add(request);
            msg = "任务已提交";
            Show_ViewText(string.Format("未分配任务数 ：{0}",TaskNoAllotList.Count.ToString()));
            //if (allotTask(request))
            //{
            //    msg = "任务已分配";
            //}
            //else
            //{
            //    msg = "任务未分配";
            //}
            return true;
        }
        public static int GetTaskNoEndCount()
        {
            if (TaskList != null)
                return TaskList.Count;
            return -1;
        }
        public static int GetTaskNoAllotCount()
        {
            if (TaskNoAllotList != null)
                return TaskNoAllotList.Count;
            return -1;
        }
        /// <summary>
        /// 新增一个执行节点
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static string EnrollNode(TaskRequest request)
        {
            //判断节点是否存在
            Worker mywk = JsonConvert.DeserializeObject(request.Param, typeof(Worker)) as Worker;
            Worker myexitk = CheckExitWorker(mywk);
            if (myexitk != null)
            {
                myexitk.LastEcho = DateTime.Now;
                Show_ViewText(string.Format("执行节点更新最后在线时间 ：{0}", myexitk.ID));
                return "更新最后在线时间";
            }
            if (mywk.MaxTaskCount <= 0)
            {
                mywk.MaxTaskCount = 500;
            }
            mywk.Enable = true;
            mywk.LastEcho = DateTime.Now;
            TaskSendNode mytsn = new TaskSendNode();
            mytsn.AppWorker = mywk;
            mywk.AppTaskNode = mytsn;
            Workers.Add(mywk);
            Show_ViewText(string.Format("新增一个执行节点 ：{0}", mywk.ID));
            return "新增一个执行节点"; 
        }
        /// <summary>
        /// 注销一个
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static string LogoutNode(TaskRequest request)
        {
            Worker mywk = JsonConvert.DeserializeObject(request.Param, typeof(Worker)) as Worker;
            Worker myexitk = CheckExitWorker(mywk);
            if (myexitk != null)
            {
                //所有已经分配没有完成的任务，重新做分配
                foreach (TaskRequest mytr in myexitk.TaskList)
                { 
                    TaskNoAllotList.Add(mytr); 
                }
                Workers.Remove(myexitk); 
                return "移除一个执行节点";
            } 
            return "执行节点不存在";
        }
        /// <summary>
        /// 任务执行结果反馈
        /// </summary>
        /// <param name="vtaskreply"></param>
        /// <returns></returns>
        public static string ReplyNode(TaskReply vtaskreply)
        {
            string msg="";
            Show_ViewText(string.Format("任务反馈 ：{0} {1}", vtaskreply.ID, vtaskreply.Status));
            if (vtaskreply.Status == 2)
            {
                msg = "任务执行成功";
                //执行成功的情况下 移除任务列表
                if (TaskReplyList.Remove(vtaskreply))
                {
                    msg += "\r\n移除结果队列";
                }
                if (TaskList.Remove(vtaskreply.TaskInfo))
                {
                    msg += "\r\n移除任务队列";
                }

                Worker mywk = findWorker(vtaskreply.NodeWorkID);
                if (mywk != null)
                {
                    mywk.TaskList.Remove(vtaskreply.TaskInfo);
                }
                DAL.SqliteDAL.SaveTaskReply(vtaskreply);
                return msg;
            }
            
            if (vtaskreply.Status == 3)
            {
                msg = "任务执行失败";
                //添加失败任务队列中
                vtaskreply.TaskInfo.ReplyTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
                msg += "\r\n添加失败任务队列";
                TaskReplyErrList.Add(vtaskreply);
                if (TaskReplyList.Remove(vtaskreply))
                {
                    msg += "\r\n移除结果队列";
                }
                if (TaskList.Remove(vtaskreply.TaskInfo))
                {
                    msg += "\r\n移除任务队列";
                }
                Worker mywk = findWorker(vtaskreply.NodeWorkID);
                if (mywk != null)
                {
                    mywk.TaskList.Remove(vtaskreply.TaskInfo);
                }
                DAL.SqliteDAL.SaveTaskReplyErr(vtaskreply);
                return msg;
            }
            TaskReply ftr = TaskReplyList.findTaskReply(vtaskreply);

            if (ftr == null)
            {
                TaskReplyList.Add(vtaskreply);
                return "添加任务反馈信息";
            }
            else
            {
                TaskReplyList.Remove(ftr);
                TaskReplyList.AddNew(vtaskreply);
                return "更新任务反馈信息";
            }
             
        }
        public static Worker findWorker(String id)
        {
            int ic = Workers.Count;
            for (int i = 0; i < ic; i++)
            {
                if (Workers[i].ID == id)
                {
                    return Workers[i];
                }
            }
            return null;
        }
            /// <summary>
            /// 判断节点是否存在
            /// </summary>
            /// <param name="mywk"></param>
            /// <returns></returns>
            public static Worker CheckExitWorker(Worker mywk)
        {
           int ic= Workers.Count;
            for (int i = 0; i < ic; i++)
            {
                if (Workers[i].Host == mywk.Host && Workers[i].Port == mywk.Port) 
                {
                    return Workers[i];
                }
            }
            return null;
        }
        /// <summary>
        /// 分配任务
        /// </summary>
        /// <param name="request"></param>
        public static Boolean allotTask(TaskRequest request)
        {
            string msg;
            Worker mywork = GetWorker_Min(out msg);
            if (mywork == null)
            {
                TaskNoAllotList.Add(request);
                return false;
            }

            TaskReply myt ;
            myt = mywork.RunTask(request);
            if (myt.Status == 4)
            {
                if (TaskNoAllotList.Contains(request))
                {
                    TaskNoAllotList.Remove(request);
                }
                Show_ViewText(string.Format("未分配任务数 ：{0}", TaskNoAllotList.Count.ToString()));
                //mywork.TaskList.Add(request);
                return true;
            }
            TaskNoAllotList.Add(request);
            return false;
        }
        
        /// <summary>
        /// 最小任务数
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        private static Worker GetWorker_Min(out string msg)
        {
            if (Workers.Count == 0)
            {
                msg = "没有执行节点";
                return null;
            }
            if (Workers.Count == 1)
            {
                msg = "只有一个执行节点";
                return Workers[0];
            }
            msg = "";
            int wc = Workers.Count;
            int lastc = -1;
            Worker lastw = null;
            for (int i = 0; i < wc; i++)
            {
                if (Workers[i].Enable)
                {
                    if (string.IsNullOrWhiteSpace(Workers[i].Host))
                    {
                        continue;
                    }
                    if (Workers[i].MaxTaskCount > Workers[i].TaskList.Count)
                    {
                        if (lastc == -1)
                        {
                            lastc = Workers[i].TaskList.Count;
                            lastw = Workers[i];
                        }
                        else
                        {
                            if (lastc > Workers[i].TaskList.Count)
                            {
                                lastc = Workers[i].TaskList.Count;
                                lastw = Workers[i];
                            }
                        }
                    }
                }
            }
            if (lastw == null)
            {
                msg = "没有有效的可分配的节点";
                return null;
            }
            return lastw;
        }
        /// <summary>
        /// 轮询查找
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        private static Worker GetWorker_Roll(out string msg)
        {
            if (Workers.Count == 0)
            {
                msg = "没有执行节点";
                return null;
            }
            msg = "";
            int wc = Workers.Count;
            LastWorkNum++;
            if (LastWorkNum >= Workers.Count)
            {
                LastWorkNum = 0;
            }

            for (int i = LastWorkNum; i < wc; i++)
            {
                if (Workers[i].Enable)
                {
                    return Workers[i];
                }
                if (Workers[i].MaxTaskCount > Workers[i].TaskList.Count)
                {
                    return Workers[i];
                }
            }
            for (int i = 0; i < wc; i++)
            {
                if (Workers[i].Enable)
                {
                    return Workers[i];
                }
                if (Workers[i].MaxTaskCount > Workers[i].TaskList.Count)
                {
                    return Workers[i];
                }
            }

            msg = "没有有效的可分配的节点";
            return null;
        }

    }
}
